module(...,package.seeall)

local fileSize
-- 处理完毕后剩余的待处理大小
tmpLeftSize, tmpFilePos = 0, 0
-- 飞控升级状态
-- 默认为false；当它为true的时候，则处于升级流程，除非升级完毕，否则始终是true；升级完毕后变为false
fcUpdateProc = false
-- 当前飞控处理事务的状态
fcUpdateSta = ""
-- 当前飞控处理的部分0/407/405（上电默认是0，每处理一个部分，判断一次，新值是否和该值相同）
fcCurUpd = "0"



local function packFrame(msg)
	return string.char(0x27)..string.char(#msg)..msg..string.char(0x20)
end



--收到消息，开始准备升级
sys.taskInit(function()
	while true do
		sys.waitUntil("FC_UPD_START")
		log.info('fcupd', 'recv fc_upd_start')
		
		--如果当前不是正在升级状态，修改状态
		if fcUpdateProc~=true then
			fcUpdateProc = true
			log.info('fcupd', 'change fcupdateproc state to true')
			
			sys.wait(1000)
			
			--升级的准备工作
			--修改波特率
			clib.uartSetup(mainFrame.uartID, 57600)
			
			--发K++
			fcUpdateSta = "FC_SEND_STR_KPP"
			sys.wait(1000)
			log.info("fcUpd", "send K++")
			uart.write(mainFrame.uartID, "K++")
			
			--重启，进入BL模式
			fcUpdateSta = "FC_REBOOT_BL"
			sys.wait(2500)
			log.info("fcUpd", "fc reboot")
			tmpData=(("a1f7eef6f69cfefefcfcfefefefefefefefefefefefefefefefefefefefefefefefe49fef6f6fe5a4f"):fromHex())
			log.info("tmpData", tmpData)
			log.info("tmpData", #tmpData)
			uart.write(mainFrame.uartID, tmpData)
			--[[sys.wait(1000)
			uart.write(mainFrame.uartID, tmpData)]]
			log.info("restartCMD", (tmpData:toHex()))
			
			--清除串口接收的缓存
			mainFrame.uartQueue={}
			
			sys.wait(1000)
			
			--修改波特率
			clib.uartSetup(mainFrame.uartID, 460800)
			
			sys.wait(1000)
			
			--如果当前队列长度>0，则开始下载，否则可能是队列出错，则结束升级
			if #mainFrame.fcFWT>0 then
				sys.publish("FC_UPD_DWN")
				log.info('fcupd', 'send FC_UPD_DWN msg')
			else
				sys.publish("FC_UPD_DONE")
				log.info('fcupd', 'send FC_UPD_DONE msg')
			end
	
		else
			log.info('fcupd', 'upgrade processing, skip')
		end
		
	end
end)

--收到消息，下载飞控包
sys.subscribe("FC_UPD_DWN", function()
	local fcUrl = mainFrame.fcFWT[1]["url"]
	log.info('fcupd', 'start to download fc part', fcUrl)
	
	io.rmFile("/fc/kpp.firmware")
	--请求下载升级固件
	table.insert(mainFrame.httpReq, {Opera="dlFcPart", Url=fcUrl, Method="GET", downFile="/fc/kpp.firmware", maxTry=10, Retry=0})
end)

--发407/405字段
sys.taskInit(function()
	while true do
		log.info("updfc", "wait for FC_UPD_SND_40X")
		sys.waitUntil("FC_UPD_SND_40X")
		--如果是407则发407内容
		if mainFrame.fcFWT[1]["type"]=="407" then
			--开始407过程
			--发字符串
			fcUpdateSta = "FC_SEND_KUDP_407_STR"
			sys.wait(2500)
			log.info("fcUpd", "send K++UPDATE407:USART2")
			uart.write(mainFrame.uartID, "K++UPDATE407:USART2")
			sys.wait(100)
			log.info("fcUpd", "send K++UPDATE407:USART2")
			uart.write(mainFrame.uartID, "K++UPDATE407:USART2")
			fcCurUpd = "407"
		
		--否则发405
		else
			--开始405过程
			sys.wait(1500)
			sys.publish("FC_UPD_REBOOT")
			sys.wait(2000)
			fcUpdateSta = "FC_SEND_KUDP_405_STR"
			sys.wait(500)
			log.info("fcUpd", "send K++UPDATE405:USART2")
			uart.write(mainFrame.uartID, "K++UPDATE405:USART2")
			sys.wait(50)
			log.info("fcUpd", "send K++UPDATE405:USART2")
			uart.write(mainFrame.uartID, "K++UPDATE405:USART2")
			fcCurUpd = "405"
		end
		
		--同步
		fcUpdateSta = "FC_SYNC"
		sys.wait(500)
		log.info("fcUpd", "send sync cmd")
		uart.write(mainFrame.uartID, (string.fromHex("2120")))
		--收到回应后，再进行下一步
		while true do sys.waitUntil("FC_SYNC_DONE") break end
		
		--清除
		fcUpdateSta = "FC_ERASE"
		sys.wait(500)
		log.info("fcUpd", "send erase cmd")
		uart.write(mainFrame.uartID, (string.fromHex("2320")))
		--收到回应后，再进行下一步
		while true do sys.waitUntil("FC_ERASE_DONE") break end
		
		--写文件
		sys.publish("FC_UPD_WRITE_FILE")
	end
end)

--写文件
sys.taskInit(function()
	while true do
		log.info("updfc", "wait for FC_UPD_WRITE_FILE")
		sys.waitUntil("FC_UPD_WRITE_FILE")
		--写文件
		fcUpdateSta = "FC_SEND_FILE"
		log.info("updFC", "receive FC_UPD_WRITE_FILE")
		sys.wait(100)
		fileLen = io.fileSize("/fc/kpp.firmware")
		tmpLeftSize = fileLen
		tmpFilePos = 0
		--先写入第一帧，后边用循环发出
		uart.write(mainFrame.uartID, packFrame(io.readStream("/fc/kpp.firmware", tmpFilePos, 128)))
		log.info("upd.send.pos", tmpFilePos, tmpLeftSize, fileLen, mainFrame.fcFWT[1]["type"], mainFrame.fcFWT[1]["sort"])
		log.info("test", packFrame(io.readStream("/fc/kpp.firmware", tmpFilePos, 128)):toHex())
		
		while true do
			log.info("updfc", "wait for FC_SEND_FILE_DONE")
			sys.waitUntil("FC_SEND_FILE_DONE")
			log.info("upd.send.pos", tmpFilePos, tmpLeftSize, fileLen, mainFrame.fcFWT[1]["type"], mainFrame.fcFWT[1]["sort"])
			if tmpLeftSize~=0 then
				uart.write(mainFrame.uartID, packFrame(io.readStream("/fc/kpp.firmware", tmpFilePos, 128)))
				log.info("test", packFrame(io.readStream("/fc/kpp.firmware", tmpFilePos, 128)):toHex())
				
			else
				if io.readStream("/fc/kpp.firmware", tmpFilePos, fileLen-tmpFilePos)~=nil then
					uart.write(mainFrame.uartID, packFrame(io.readStream("/fc/kpp.firmware", tmpFilePos, fileLen-tmpFilePos)))
					log.info("test", packFrame(io.readStream("/fc/kpp.firmware", tmpFilePos, fileLen-tmpFilePos)):toHex())
				end
				log.info("upd.send.complete")
				break
			end
		end
		
		--删除当前已经下载的固件
		io.rmFile("/fc/kpp.firmware")
		log.info('fcupd', 'write current pkg done')
		
		--写入文件完毕，根据table的剩余项目数判断，后续是继续下载、重启操作
		--如果表剩余大于1
		if #mainFrame.fcFWT>1 then
			table.remove(mainFrame.fcFWT, 1)
			sys.publish("FC_UPD_DWN")

		--当前列表只有一个，或者0个，那么就是最后一个了，清空并重启
		else
			mainFrame.fcFWT={}
			sys.publish("FC_UPD_REBOOT")
		end
			
		
	end
end)

--重启飞控
sys.taskInit(function()
	while true do
		sys.waitUntil("FC_UPD_REBOOT")
		--重启
		fcUpdateSta = "FC_REBOOT"
		sys.wait(1500)
		log.info("fcUpd", "reboot fc")
		uart.write(mainFrame.uartID, (string.fromHex("3020")))
		
		
		sys.wait(1000)
		--如果队列里是0个，则升级完成
		if #mainFrame.fcFWT==0 then
			sys.publish("FC_UPD_DONE")
			log.info('fcupd', 'fc reboot. update done')
		end
	end
end)


--升级完成
sys.subscribe("FC_UPD_DONE", function()
	--修改波特率
	clib.uartSetup(mainFrame.uartID, 57600)
	
	-- 处理完毕后剩余的待处理大小
	tmpLeftSize, tmpFilePos = 0, 0
	-- 飞控升级状态
	-- 默认为false；当它为true的时候，则处于升级流程，除非升级完毕，否则始终是true；升级完毕后变为false
	fcUpdateProc = false
	-- 当前飞控处理事务的状态
	fcUpdateSta = ""
	-- 当前飞控处理的部分0/407/405（上电默认是0，每处理一个部分，判断一次，新值是否和该值相同）
	fcCurUpd = "0"
	
	io.rmFile("/fc/kpp.firmware")

	log.info('fcupd', 'change fcupdateproc state to false')
end)




